package cn.tedu.charging.order.mqtt;

import cn.tedu.charging.common.utils.JsonUtils;
import cn.tedu.charging.order.constant.Constants;
import cn.tedu.charging.order.constant.MqttConstant;
import cn.tedu.charging.order.constant.OrderStatusConstant;
import cn.tedu.charging.order.pojo.dto.ChargingResultDto;
import cn.tedu.charging.order.pojo.po.ChargingBillFailPO;
import cn.tedu.charging.order.pojo.po.ChargingBillSuccessPO;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.paho.client.mqttv3.*;


/**
 * EMQX的消息中间的 消费者
 * 订单服务 用来 接收(订阅 subscribe) 设备发送的消息
 */
@Slf4j
public class MqttConsumer implements MqttCallbackExtended {
    private final MqttClient mqttClient;
    private MqttContext mqttContext;

    public MqttConsumer(MqttContext mqttContext, MqttClient mqttClient) {
        this.mqttContext = mqttContext;
        this.mqttClient = mqttClient;
    }

    @Override
    public void connectComplete(boolean reconnect, String serverURI) {
        log.debug("MqttConsumer#connectComplete方法被调用了,表示连接成功," +
                "reconnect:{},serverURI:{}", reconnect, serverURI);
        try {
            log.debug("连接成功,订阅开始充电指令的响应topic:{}", MqttConstant.TOPIC_CHARGING_RESULT);
            mqttClient.subscribe(MqttConstant.TOPIC_CHARGING_RESULT);
            log.debug("连接成功,订阅开始充电指令的请求topic:{},成功", MqttConstant.TOPIC_CHARGING_RESULT);
        } catch (MqttException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public void connectionLost(Throwable cause) {
        log.debug("MqttConsumer#connectionLost方法被调了,表示连接丢失了", cause);

    }


    /**
     * 订单服务 用来 订阅 设备发送的消息
     *
     * @param topic
     * @param mqttMessage
     * @throws Exception
     */
    @Override
    public void messageArrived(String topic, MqttMessage mqttMessage) throws Exception {
        log.debug("MqttConsumer#messageArrived方法被调了,表示收到消息了," +
                "topic:{},message:{}", topic, mqttMessage);
        ChargingResultDto chargingResultDto = null;
        try {
            // 把设备发送的消息JSON转换为java对象 ChargingResultDto
            chargingResultDto = JsonUtils.fromJson(mqttMessage.toString(), ChargingResultDto.class);
            log.debug("收到开始充电结果消息:{}", chargingResultDto);
        } catch (Exception e) {
            log.error("设备消息发送的开始充电结果消息{}格式有问题,请检查!", mqttMessage, e);
        }

        //判断设备返回的响应不能为空
        if (chargingResultDto != null) {
            //获取设备响应对象
            String result = chargingResultDto.getResult();
            //判断设备响应结果
            if (Constants.RESULT_START_CHARGING_SUCCESS.equals(result)) {
                saveSuccessOrder(chargingResultDto);

            } else {

                log.debug("通知用户,表示歉意,提醒用户更换充电枪");
                log.debug("通知设备管理人员,进行设备检修");
                saveFailOrder(chargingResultDto);
            }
        }
    }

    private void saveSuccessOrder(ChargingResultDto chargingResultDto) {
        log.debug("设备有响应,充电桩开始充电成功");
        ChargingBillSuccessPO po = new ChargingBillSuccessPO();
        po.setBillId(chargingResultDto.getOrderNo());
        //设置订单状态为充电中
        po.setBillStatus(OrderStatusConstant.ORDER_STATUS_PROGRESS);
        log.debug("保存成功订单记录:{}", po);
        Integer row = mqttContext.getOrderSuccessMapper().saveOrderByMybatis(po);
        log.debug("保存成功订单记录:{},成功,影响行数:{}", po, row);
    }

    private void saveFailOrder(ChargingResultDto chargingResultDto) {
        log.debug("设备有响应,但充电桩开始充电失败");
        ChargingBillFailPO chargingBillFailPO = new ChargingBillFailPO();
        chargingBillFailPO.setBillId(chargingResultDto.getOrderNo());
        chargingBillFailPO.setFailDesc("充电站故障-无法正常充电");
        log.debug("保存失败订单记录:{}", chargingBillFailPO);
        Integer row = mqttContext.getOrderFailMapper().insert(chargingBillFailPO);
        log.debug("保存失败订单记录:{},完成,影响行数:{}", chargingBillFailPO, row);
    }

    @Override
    public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) {
        log.debug("MqttConsumer#deliveryComplete方法被调了,表示消息分发完成");
    }
}
